package cn.pconline.test;

import static org.junit.Assert.assertNotNull;

import javax.naming.NamingException;
import javax.resource.spi.ResourceAdapterInternalException;

import org.gelivable.web.Env;
import org.gelivable.web.EnvUtils;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.mock.jndi.SimpleNamingContextBuilder;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.mock.web.MockServletContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.TestExecutionListeners;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.support.DependencyInjectionTestExecutionListener;
import org.springframework.test.context.support.DirtiesContextTestExecutionListener;
import org.springframework.test.context.transaction.TransactionalTestExecutionListener;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
import org.springframework.web.context.support.XmlWebApplicationContext;

import cn.pconline.autoclub.web.UserAuth;
import cn.pconline.r.route.PcRouteJNDI;

/**
 *
 * @author chenchongqi
 */
@RunWith(SpringJUnit4ClassRunner.class)
@TestExecutionListeners({DependencyInjectionTestExecutionListener.class,
    DirtiesContextTestExecutionListener.class,
    TransactionalTestExecutionListener.class})
@ContextConfiguration(locations = {
    "classpath:applicationContext.xml",
    "classpath:autoclub-passport.xml",
    "classpath:autoclub-servlet.xml",
    "classpath:autoclub-systemConfig.xml"})
public class AbstractTestCase {
    
    protected final Logger log = LoggerFactory.getLogger(getClass());

    public static final String testBasePath = "target/test-classes/";

    public static MockHttpServletRequest getRequest() {
        EnvUtils.getEnv().setRequest(new MockHttpServletRequest());
        return (MockHttpServletRequest) EnvUtils.getEnv().getRequest();
    }

    public static MockHttpServletResponse getResponse() {
        EnvUtils.getEnv().setResponse(new MockHttpServletResponse());
        return (MockHttpServletResponse) EnvUtils.getEnv().getResponse();
    }

    private static void setEnv() {
        String[] paths = {
            "classpath:applicationContext.xml",
            "classpath:autoclub-passport.xml",
            "classpath:autoclub-servlet.xml",
            "classpath:autoclub-systemConfig.xml"};
        XmlWebApplicationContext ctx = new XmlWebApplicationContext();
        ctx.setConfigLocations(paths);
        ctx.refresh();
        MockServletContext servletContext =
                new MockServletContext();
        servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE,
                ctx);
        WebApplicationContext wc = WebApplicationContextUtils.getWebApplicationContext(servletContext);
        assertNotNull(wc);
        Env env = EnvUtils.getEnv();
        env.setRequest(new MockHttpServletRequest());
        env.setResponse(new MockHttpServletResponse());
        env.setServletContext(servletContext);
    }

    public void login(long accountId, MockHttpServletRequest request) {
        //登录
        UserAuth userAuth = EnvUtils.getEnv().getBean(UserAuth.class);
        request.setAttribute("user", userAuth.authUser(accountId));
    }

    static {
        try {
            //Init all related jndi bindings for non web container test cases.
            SimpleNamingContextBuilder builder = SimpleNamingContextBuilder.emptyActivatedContextBuilder();
            //Env config file, which define in pom.xml test resources.
            builder.bind("java:comp/env/props", "target/test-classes/autoclub.properties");
            builder.bind("java:comp/env/app-name", "autoclub");
            builder.bind("java:comp/env/app-name-override", "autoclub");

            DriverManagerDataSource dataSource = new DriverManagerDataSource();
            dataSource.setDriverClassName("com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource");
            dataSource.setUrl("jdbc:mysql://192.168.75.99:3306/autoclub?useUnicode=true&amp;characterEncoding=UTF-8");
            dataSource.setUsername("autoclub");
            dataSource.setPassword("autoclub");
            builder.bind("jdbc/autoclub", dataSource);

            builder.bind("java:comp/env/memCachedClientConfig4RClient",
                    "servers=127.0.0.1:11221\n"
                    + "initConn=20\n"
                    + "minConn=10\n"
                    + "maxConn=50\n"
                    + "maintSleep=30\n"
                    + "nagle=false\n"
                    + "socketTO=3000");

            //R jndi bindings, not config mc for function tests usage.
            PcRouteJNDI pcRouteJndi = new PcRouteJNDI();
            pcRouteJndi.setRouteUri("http://192.168.75.1/route.txt");
            pcRouteJndi.setDnsAddr("192.168.11.228");
            try {
                pcRouteJndi.start(null);
            } catch (ResourceAdapterInternalException ex) {
                ex.printStackTrace();
            }

            builder.bind("jca/pc_route", pcRouteJndi);

            builder.activate();
            //This is default test output directory, 
            //if changed in pom.xml please modify this bingding too.
        } catch (NamingException ex) {
            ex.printStackTrace();
        }
    }

    @BeforeClass
    public static void setUpClass() {
        setEnv();
        //还原数据库
        /*JdbcTemplate jdbcTemplate = EnvUtils.getEnv().getJdbcTemplate();
        String allTables = "show table status from autoclub_app";
        final List<String> tableList = new ArrayList<String>();
        jdbcTemplate.query(allTables, new RowCallbackHandler() {
            @Override
            public void processRow(ResultSet rs) throws SQLException {
                tableList.add(rs.getString("Name"));
            }
        });
        for (String t : tableList) {
            jdbcTemplate.execute(String.format("drop table %s", t));
        }
        File initSqlFile = new File(testBasePath + "sql/autoclub.sql");
        try {
            List<String> sqls = new ArrayList<String>(256);
            StringBuilder sql = new StringBuilder();
            BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(initSqlFile), Charset.forName("UTF-8")));
            String cur = reader.readLine();
            while (cur != null) {
                if (StringUtils.isBlank(cur)) {
                    cur = reader.readLine();
                    continue;
                }
                sql.append(cur);
                if (cur.endsWith(";")) {
                    //删除注释 分隔符
                    String s = sql.toString().replaceAll("\\/\\*[\\S\\s]*?\\*\\/", "").replaceAll(";", " ").trim();
                    if (StringUtils.isBlank(s)) {
                        cur = reader.readLine();
                        continue;
                    }
                    sqls.add(s);
                    sql = new StringBuilder();
                }
                cur = reader.readLine();
            }
            String[] sqlArr = new String[sqls.size()];
            for (int i = 0; i < sqls.size(); i++) {
                sqlArr[i] = sqls.get(i);
            }
            jdbcTemplate.batchUpdate(sqlArr);
        } catch (FileNotFoundException ex) {
            Logger.getLogger(AbstractTestCase.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            Logger.getLogger(AbstractTestCase.class.getName()).log(Level.SEVERE, null, ex);
        }*/
    }

    @AfterClass
    public static void tearDownClass() {
    }
}
